/* Copyright (c) 2004-2008, Andriy Nikolov
 * All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.processmining.email;

import java.util.*;

/**
 * <p>A class containing the weight matrix of the case-person diagram
 *
 * @author Andriy Nikolov
 * @version 1.0
 */
public class CasePersonTable {
  Vector caseList, personList;
  ProcessLog processLog;
  double normalizedWeights[][];
  int absoluteWeights[][];
  boolean peopleConnected[];

  public CasePersonTable() {
    jbInit();
  }

  public CasePersonTable(ProcessLog log) {
    processLog = log;
    jbInit();
  }

  public ProcessLog getProcessLog() {
    return processLog;
  }

  public void setProcessLog(ProcessLog log) {
    processLog = log;
  }

  private void jbInit() {
    caseList = new Vector();
    personList = new Vector();
  }

  public Vector getCaseList() {
    return caseList;
  }

  public Vector getPersonList() {
    return personList;
  }

  private void getAllCases() {
    ProcessCase curCase;
    String curName;

    caseList.clear();
//    caseList = processLog.getOrderedCaseList();
    for(int i=0;i<processLog.getOrderedCaseList().size();i++) {
      curCase = (ProcessCase)processLog.getOrderedCaseList().get(i);
      curName = curCase.getDescription();
      caseList.add(curName);
    }
  }

  private void getAllPeople() {
    EMailRecipient currentPerson;
    EMailLog eMailLog;
    personList.clear();
    eMailLog = processLog.getEMailLog();
    for(int i=0;i<eMailLog.getEmployeesList().size();i++) {
      currentPerson = (EMailRecipient)eMailLog.getEmployeesList().get(i);
      if(currentPerson.isActive()) {
        personList.add(currentPerson.getName());
      }
    }
  }

  private void calculateWeights() {
    ProcessCase currentCase;
    ProcessEvent currentEvent;
    EMailMessage currentMessage;
    EMailRecipient currentRecipient;
    int i, j, k;

    absoluteWeights = new int[caseList.size()][personList.size()];
    peopleConnected = new boolean[personList.size()];
    for(i=0;i<caseList.size();i++) {
      for(j=0;j<personList.size();j++) {
        absoluteWeights[i][j] = 0;
      }
    }
    for(j=0;j<personList.size();j++) {
        peopleConnected[j] = false;
    }

    for(i=0;i<processLog.getOrderedCaseList().size();i++) {
      currentCase = (ProcessCase)processLog.getOrderedCaseList().get(i);
      for(j=0;j<currentCase.getEventList().size();j++) {
        currentEvent = (ProcessEvent)currentCase.getEventList().get(j);
        currentMessage = (EMailMessage)currentEvent.getEMailMessage();
        currentRecipient = currentMessage.getFrom();
        incWeight(currentCase.getDescription(), currentRecipient.getName());
        for(k=0;k<currentMessage.getTo().size();k++) {
          currentRecipient = (EMailRecipient)currentMessage.getTo().get(k);
          incWeight(currentCase.getDescription(), currentRecipient.getName());
        }
        for(k=0;k<currentMessage.getCc().size();k++) {
          currentRecipient = (EMailRecipient)currentMessage.getCc().get(k);
          incWeight(currentCase.getDescription(), currentRecipient.getName());
        }
        for(k=0;k<currentMessage.getBcc().size();k++) {
          currentRecipient = (EMailRecipient)currentMessage.getBcc().get(k);
          incWeight(currentCase.getDescription(), currentRecipient.getName());
        }
      }
    }
  }

  private void normalizeWeights() {
    int max;
    int i, j;
    normalizedWeights = new double[caseList.size()][personList.size()];
    max = 1;

    for(i=0;i<caseList.size();i++) {
      for(j=0;j<personList.size();j++) {
        if(absoluteWeights[i][j]>max) {
          max = absoluteWeights[i][j];
        }
      }
    }
    for(i=0;i<caseList.size();i++) {
      for (j = 0; j < personList.size(); j++) {
        normalizedWeights[i][j] = absoluteWeights[i][j];
        normalizedWeights[i][j] /= max;
      }
    }
  }

  private void incWeight(String caseName, String personName) {
    int indexcase, indexPerson;
    try {
      indexcase = caseList.indexOf(caseName);
      indexPerson = personList.indexOf(personName);
      absoluteWeights[indexcase][indexPerson]++;
      peopleConnected[indexPerson] = true;
    } catch (ArrayIndexOutOfBoundsException e) {
      System.err.println(caseName);
      System.err.println(personName);
//      e.printStackTrace();
    }
  }

  /**
   * calculateTable - calculates the weights of the case-person diagram
   */
  public void calculateTable() {
    getAllCases();
    getAllPeople();
    calculateWeights();
    normalizeWeights();
  }

  /**
   * Gets the absolute weight of the arc connecting the caseNum-th case node
   * with the personNum-th person node
   *
   * @param caseNum int
   * @param personNum int
   * @return int
   */
  public int getAbsoluteWeight(int caseNum, int personNum) {
    return absoluteWeights[caseNum][personNum];
  }

  /**
     * Gets the normalized weight of the arc connecting the caseNum-th case node
     * with the personNum-th person node
     *
     * @param caseNum int
     * @param personNum int
     * @return int
   */
  public double getNormalizedWeight(int caseNum, int personNum) {
    return normalizedWeights[caseNum][personNum];
  }

  /**
   * Gets the absolute weight of the arc connecting the case node with the name
   * caseName and the person node with the name personName
   *
   * @param caseName String
   * @param personName String
   * @return int
   */
  public int getAbsoulteWeight(String caseName, String personName) {
    try {
      return absoluteWeights[caseList.indexOf(caseName)][personList.indexOf(personName)];
    } catch(Exception e) {
      System.err.println(caseName);
      System.err.println(personName);
      e.printStackTrace();
      return 0;
    }
  }

  /**
     * Gets the normalized weight of the arc connecting the case node with the name
     * caseName and the person node with the name personName
     *
     * @param caseName String
     * @param personName String
     * @return int
   */
  public double getNormalizedWeight(String caseName, String personName) {
    try {
      return normalizedWeights[caseList.indexOf(caseName)][personList.indexOf(personName)];
    } catch(Exception e) {
      System.err.println(caseName);
      System.err.println(personName);
      e.printStackTrace();
      return 0;
    }
  }

  public boolean isPersonConnected(String personName) {
    try {
      return peopleConnected[personList.indexOf(personName)];
    } catch(Exception e) {
      e.printStackTrace();
      return false;
    }
  }
}
